/*
 * @Author: 0x9DEFA478
 * @Date: 2025-06-21 20:25:44
 * @LastEditTime: 2025-09-23 21:16:53
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#include "./C_ArgumentDecode.hpp"
#include "./Tree/H_Tree_RedBlack.hpp"
#include <stdexcept>




static int DecodeOption(const char* arg){
  int r;
  char c;

  if(arg[0]!='-'){
    return -1;
  }
  if(arg[1]=='\0'){
    return -1;
  }
  if(arg[1]!='-'){
    return 2;
  }
  
  r=1;
  do{
    r++;
    c=arg[r];
  }while((c!='=')&&(c!='\0'));

  return r;
}

struct PrivateData{
  H::Tree::RedBlack<std::string,H::ArgumentDecode::Option*> optMap;
  std::vector<std::string> remanderArgument;

  void AddOption(H::ArgumentDecode::Option* option);
  H::ArgumentDecode::Option* FindOption(const std::string& option)noexcept;
};

void PrivateData::AddOption(H::ArgumentDecode::Option* option){
  optMap.Insert(option->GetOption(),option);
}

H::ArgumentDecode::Option* PrivateData::FindOption(const std::string& option)noexcept{
  auto res=optMap.Find(option);
  if(res==optMap.end()){
    return nullptr;
  }
  return res->Data();
}


namespace H{

  ArgumentDecode::ArgumentDecode()noexcept
    :Valid_EndArgMark(false)
    ,privateData(static_cast<void*>(new PrivateData))
  {}

  ArgumentDecode::ArgumentDecode(const std::string EndArgMark)noexcept
    :EndArgMark(EndArgMark),Valid_EndArgMark(true)
    ,privateData(static_cast<void*>(new PrivateData))
  {}

  ArgumentDecode::~ArgumentDecode()noexcept{
    delete static_cast<PrivateData*>(privateData);
  }

  void ArgumentDecode::AddOption(Option* option){
    auto privateData=static_cast<PrivateData*>(this->privateData);
    privateData->AddOption(option);
  }

  const std::vector<std::string>& ArgumentDecode::GetRemanderArgument()noexcept{
    auto privateData=static_cast<PrivateData*>(this->privateData);
    return privateData->remanderArgument;
  }

  void ArgumentDecode::Decode(int argc,const char* const* argv){
    auto privateData=static_cast<PrivateData*>(this->privateData);

    for(int i=1;i<argc;i++){
      const char* arg;
      Option* opt;
      int paramIndex;

      arg=argv[i];

      if(Valid_EndArgMark){
        if(EndArgMark.compare(arg)==0){
          for(int index=i+1;index<argc;index++){
            privateData->remanderArgument.emplace_back(argv[index]);
          }
          privateData->remanderArgument.shrink_to_fit();
          return;
        }
      }

      paramIndex=DecodeOption(arg);
      if(paramIndex<2){
        privateData->remanderArgument.emplace_back(arg);
        continue;
      }

      opt=privateData->FindOption(std::string(arg,paramIndex));
      if(opt==nullptr){
        throw std::invalid_argument("不支持的选项\""+std::string(arg)+"\"");
      }

      opt->isSet=true;
      if(arg[paramIndex]=='='){
        opt->value=std::string(&arg[paramIndex+1]);
        opt->valueValid=true;
      }else{
        opt->valueValid=false;
      }

      privateData->remanderArgument.shrink_to_fit();
    }

  }


}

